package cn.tedu.charging.order.websocket;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
@Component
@ServerEndpoint("/ws/server/{userId}")
public class WebSocketServer {

    /**
     * ConcurrentHashMap是线程安全的map JUC(java.util.concurrent)
     * 用来存放 每个用户对应的session 会话状态
     * key 用户id
     * value 会话session
     *
     * 本地map 在内存里,重启后,数据就清空了,session清空了
     * 清空后会导致session丢失 用户和服务端的连接断开了,
     * 持久化, 需要持久化的压力
     * 客服的聊天室
     * https://blog.csdn.net/xpfjllmm/article/details/137624364 redis持久化方案
     * https://www.51cto.com/article/785408.html 持久化
     */
    private static ConcurrentHashMap<Integer, Session> sessions = new ConcurrentHashMap<>();

    /**
     * 连接建立成功调用的方法  类似MqttConsumer的connectComplete方法
     * @param session 会话状态
     * @param userId
     */
    @OnOpen //把这个改成static，才能每次重启时不丢失session？忘了为啥了？？
    public void onOpen(Session session, @PathParam("userId") Integer userId) {
        log.info("onOpen");
        sessions.put(userId, session);  //将用户session存进去
        log.info("用户:{},连接成功:{}", userId, session.getId());
    }

    /**
     * session 连接关闭
     * @param session
     * @param userId
     */
    @OnClose
    public void onClose(Session session, @PathParam("userId") Integer userId) {
        sessions.remove(userId);
        log.debug("用户{},退出",userId);
    }

    /**
     * 客户端给服务端发消息
     * @param message 具体的消息
     * @param session 谁发送的
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        log.debug("用户:{},发送消息:{}",session,message);
    }

    /**
     * 发送消息 服务端主动推送消息给客户端
     * @param userId
     * @param message
     */
    public void sendMessage(Integer userId, String message){
        Session session = sessions.get(userId);
        if (session != null) {
            try {
                session.getBasicRemote().sendText(message);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }else {
            log.error("用户:{},已经下线",userId);
        }
    }

    /**
     * 出现问题时调用此方法  具体错误的原因 throwable 谁出现问题 session
     * @param session
     * @param throwable
     */
    @OnError
    public void onError(Session session, Throwable throwable) {
        log.error("onError", throwable);
    }
}
